#include "processor/DefaultProcessor.hpp"
#include <opencv2/core/mat.hpp>
#include <opencv2/core/ovx.hpp>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>

// 计算 TC 比值结果标识
std::string calculateResult(double tcRatio) {
  if (tcRatio == -1 || tcRatio == 0 || tcRatio == 0.01) {
    return "Invalid"; // 无效
  } else if (tcRatio < 0.85) {
    return "Positive"; // 阳性
  } else if (tcRatio <= 1.0) {
    return "Weak Positive"; // 弱阳性
  } else {
    return "Negative"; // 阴性
  }
}

double CalculateFWHMArea(const std::vector<double> &grayValues, int peakIndex) {
  if (peakIndex < 0 || peakIndex >= grayValues.size()) {
    return 0.0; // 如果波峰索引无效，返回 0
  }

  double peakValue = grayValues[peakIndex]; // 波峰值

  // 计算左右边界
  int left = std::max(0, peakIndex - 5); // 左侧边界
  int right = std::min(static_cast<int>(grayValues.size()) - 1,
                       peakIndex + 5); // 右侧边界

  // 计算相对面积（累加相对于波峰值的差值）
  double area = 0.0;
  for (int i = left; i <= right; ++i) {
    area += peakValue - grayValues[i];
  }

  return area;
}

// 主函数：计算 cValue、tValue 和 t/c 值
std::tuple<double, double, double>
DefaultGrayScaleProcessor::CalculatePeakAreas(
    const std::vector<double> &grayValues, int pc, int pt) {
  // 计算前半部分波峰的半峰宽面积
  double cValue = CalculateFWHMArea(grayValues, pc);

  // 计算后半部分波峰的半峰宽面积
  double tValue = CalculateFWHMArea(grayValues, pt);

  // 计算 t/c 值
  double tcRatio = (cValue != 0.0) ? (tValue / cValue) : 0.0;

  return {cValue, tValue, tcRatio};
}

void DefaultGrayScaleProcessor::ShowMat(const cv::Mat &image, int x1, int y1,
                                        int x2, int y2, int l, int pk1, int pk2,
                                        int mid) {
  // 在图像上绘制矩形框
  // cv::rectangle(image, cv::Point(x1, y1), cv::Point(x1 + l, y1 + l),
  //               cv::Scalar(255, 0, 0), 2); // 蓝色框
  // cv::rectangle(image, cv::Point(x2, y2), cv::Point(x2 + l, y2 + l),
  //               cv::Scalar(0, 255, 0), 2); // 绿色框
  // 在图像上绘制矩形框
  cv::rectangle(image, cv::Point(x1, y1), cv::Point(x2, y2),
                cv::Scalar(0, 0, 255), 2); // 蓝色框
  cv::rectangle(image, cv::Point(x1, y1 + pk1), cv::Point(x2, y1 + pk1 + 2),
                cv::Scalar(255, 0, 0), 1); // 蓝色框
  cv::rectangle(image, cv::Point(x1, y1 + pk2), cv::Point(x2, y1 + pk2 + 2),
                cv::Scalar(0, 0, 255), 1); // 蓝色框
  cv::rectangle(image, cv::Point(x1, y1 + mid), cv::Point(x2, y1 + mid + 2),
                cv::Scalar(40, 30, 92), 1); // 蓝色框

  // 显示图像
  cv::namedWindow("Image", cv::WINDOW_NORMAL);
  cv::imshow("Image", image);

  // 等待按键
  cv::waitKey(0);
}
// 计算灰度值的方法（使用 sum）
std::tuple<double, double, double>
DefaultGrayScaleProcessor::CalculateGrayscale(const cv::Mat &mat, int x1,
                                              int y1, int x2, int y2, int l) {
  // 确保输入的矩形区域在图像范围内
  if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 + l > mat.cols ||
      y1 + l > mat.rows || x2 + l > mat.cols || y2 + l > mat.rows) {
    std::cerr << "矩形区域超出图像范围，请检查输入参数" << std::endl;
    return {0.0, 0.0, 0.0};
  }

  // 提取第一个矩形区域 (c)
  cv::Rect rectC(x1, y1, l, l);
  cv::Mat regionC = mat(rectC);

  // 提取第二个矩形区域 (t)
  cv::Rect rectT(x2, y2, l, l);
  cv::Mat regionT = mat(rectT);

  // 将图像转换为灰度图（如果输入不是灰度图）
  cv::Mat grayC, grayT;
  if (regionC.channels() > 1) {
    cv::cvtColor(regionC, grayC, cv::COLOR_BGR2GRAY);
    cv::cvtColor(regionT, grayT, cv::COLOR_BGR2GRAY);
  } else {
    grayC = regionC;
    grayT = regionT;
  }

  // 计算灰度值（总和）
  double sumC = cv::sum(255 - grayC)[0]; // 总和灰度值
  double sumT = cv::sum(255 - grayT)[0];

  // 防止除零错误
  double ratio = (sumC != 0) ? (sumT / sumC) : 0.0;

  return {sumC, sumT, ratio};
}

std::tuple<std::string, std::string, std::vector<double>, int, int, double,
           double, double>
DefaultGrayScaleProcessor::GetGrayScaleArray(const cv::Mat &image, int x, int y,
                                             int width, int height) {
  // 确保图像非空
  if (image.empty()) {
    std::cerr << "输入图像为空，请检查图像数据" << std::endl;
    return {};
  }

  // 计算动态矩形区域
  if (x == 0) {
    x = image.cols / 2; // 图片中线位置
  }
  if (y == 0) {
    y = image.rows / 3; // 图片 1/3 高度位置
  }
  if (width == 0) {
    width = 10; // 宽度为 10 像素 (x1-5 到 x1+5)
  }
  if (height == 0) {
    height = 100; // 高度从 y1 到 2*y1
  }

  int k = 3;
  std::vector<double> grayValues =
      GetGrayScaleArrayWithKernel(x - 5, y + 10, width, height, image, k);
  auto [pc, pt, mid] = FindPeakPoints(grayValues);
  // 调用 ShowMat 方法展示扣出来的框
  // ShowMat(image, x - 5, y + 10, x + 5, y + height, 0, pc + k, pt + k, mid +
  // k); 计算半峰宽面积和 t/c 值
  auto [cValue, tValue, tcRatio] = CalculatePeakAreas(grayValues, pc, pt);
  std::string result = calculateResult(tcRatio);
  // 返回所有结果
  return {"Success", result, grayValues, pc, pt, cValue, tValue, tcRatio};
}

// 封装函数以计算峰值点
std::tuple<int, int, int> DefaultGrayScaleProcessor::FindPeakPoints(
    const std::vector<double> &grayValues) {
  if (grayValues.empty()) {
    return {-1, -1, -1}; // 如果数组为空，返回无效值
  }

  int n = grayValues.size();
  int mid = n / 2;

  // 辅助函数：查找波峰
  auto findPeak = [](const std::vector<double> &values, int start,
                     int end) -> int {
    for (int i = start + 1; i < end - 1; ++i) {
      if (values[i] > values[i - 1] && values[i] > values[i + 1]) {
        return i; // 找到波峰
      }
    }
    return -1; // 没有找到波峰
  };

  // 查找前半部分的波峰
  int peak1 = findPeak(grayValues, 15, mid);

  // 查找后半部分的波峰
  int peak2 = findPeak(grayValues, mid, n - 15);

  return {peak1, peak2, mid};
}

std::vector<double> DefaultGrayScaleProcessor::GetGrayScaleArrayWithKernel(
    int x1, int y1, int width, int height, const cv::Mat &image, int k) {
  // 确保图像非空
  if (image.empty()) {
    std::cerr << "输入图像为空，请检查图像数据" << std::endl;
    return {};
  }

  // 矩形区域左上角和右下角坐标
  cv::Rect rect(x1, y1, width, height);

  // 检查矩形是否超出图像范围
  if (rect.x < 0 || rect.y < 0 || rect.x + rect.width > image.cols ||
      rect.y + rect.height > image.rows) {
    std::cerr << "矩形区域超出图像范围，请检查图像尺寸" << std::endl;
    return {};
  }

  // 提取矩形区域
  cv::Mat region = image(rect);

  cv::Mat redChannel, grayRegion;
  if (region.channels() > 1) {
    // 分离颜色通道
    std::vector<cv::Mat> channels;
    cv::split(region, channels);

    // 只保留红色通道
    redChannel = channels[2]; // BGR -> R is index 2

    // 转换为灰度图（直接使用红色通道）
    redChannel.convertTo(grayRegion, CV_8UC1);
  } else {
    grayRegion = region;
  }

  // 存储每一行的灰度值总和
  std::vector<double> grayValues;

  // 核大小检查
  if (k < 0 || k >= grayRegion.rows || k >= grayRegion.cols) {
    std::cerr << "参数 k 不合法，请确保 k 小于图像的高度和宽度" << std::endl;
    return {};
  }

  // 打印得到的灰度区域的宽高
  std::cout << "Gray region width: " << grayRegion.cols
            << ", height: " << grayRegion.rows << std::endl;

  // 计算灰度值
  for (int i = k; i < grayRegion.rows - k; ++i) {
    double rowSum = 0.0;

    for (int j = k; j < grayRegion.cols - k; ++j) {
      double kernelSum = 0.0;

      // 计算以 (i,j) 为中心的边长为 2k+1 的正方形区域的灰度值总和
      for (int ki = -k; ki <= k; ++ki) {
        for (int kj = -k; kj <= k; ++kj) {
          int rowIndex = i + ki;
          int colIndex = j + kj;

          if (rowIndex >= 0 && rowIndex < grayRegion.rows && colIndex >= 0 &&
              colIndex < grayRegion.cols) {
            kernelSum += 255 - grayRegion.at<uchar>(rowIndex, colIndex);
          }
        }
      }

      rowSum += kernelSum;
    }

    grayValues.push_back(rowSum);
  }

  std::cout << "Gray values length: " << grayValues.size() << std::endl;
  return grayValues;
}
